/*
 *  Copyright (C) 2012 Компания ВИТ. web: http://diasled.ru Е-mail:  vit@diasled.ru
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ru.apertum.diasled.forms;

import javax.swing.event.ListSelectionEvent;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.RowFilter;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import ru.apertum.diasled.Diasled;
import ru.apertum.diasled.common.Tray;
import ru.apertum.diasled.common.Uses;
import ru.apertum.diasled.model.Patient;
import ru.apertum.diasled.model.Visit;
import ru.apertum.diasled.model.patients.PatientsTableModel;
import ru.apertum.diasled.model.patients.VisitsTableModel;

/**
 * The application's main frame.
 * @author Evgeniy Egorov, Aperum Projects
 */
public class DiasledView extends FrameView {

    /**
     * Системный трей.
     */
    private final Tray tray;

    public DiasledView(SingleFrameApplication app) {
        super(app);

        initComponents();


        getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        // свернем по esc
        getRootPane().registerKeyboardAction(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                getFrame().setVisible(false);
            }
        },
                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        try {
            getFrame().setIconImage(ImageIO.read(DiasledView.class.getResource("/ru/apertum/diasled/forms/resources/favicon.png")));
        } catch (IOException ex) {
            System.err.println(ex);
        }

        // инициализим trayIcon, т.к. setSituation() требует работу с tray
        tray = Tray.getInstance(this.getFrame(), "/ru/apertum/diasled/forms/resources/favicon.png", "Диаслед-скан");
        tray.addItem("Диасдел-скан", new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                getFrame().setVisible(true);
                getFrame().setState(JFrame.NORMAL);
            }
        });
        tray.addItem("-", new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
            }
        });
        tray.addItem("Завершить работу", new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                getFrame().dispose();
                System.exit(0);
            }
        });

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(Diasled.getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                switch (propertyName) {
                    case "started":
                        if (!busyIconTimer.isRunning()) {
                            statusAnimationLabel.setIcon(busyIcons[0]);
                            busyIconIndex = 0;
                            busyIconTimer.start();
                        }
                        progressBar.setVisible(true);
                        progressBar.setIndeterminate(true);
                        break;
                    case "done":
                        busyIconTimer.stop();
                        statusAnimationLabel.setIcon(idleIcon);
                        progressBar.setVisible(false);
                        progressBar.setValue(0);
                        break;
                    case "message":
                        String text = (String) (evt.getNewValue());
                        statusMessageLabel.setText((text == null) ? "" : text);
                        messageTimer.restart();
                        break;
                    case "progress":
                        int value = (Integer) (evt.getNewValue());
                        progressBar.setVisible(true);
                        progressBar.setIndeterminate(false);
                        progressBar.setValue(value);
                        break;
                }
            }
        });

        tablePatients.setModel(new PatientsTableModel());
        tableVisits.setModel(new VisitsTableModel());

        final RowFilter<Object, Object> filter = new RowFilter<Object, Object>() {

            public boolean include(Entry entry) {
                if (!textFieldFilterSecondName.getText().isEmpty()) {
                    return ((String) entry.getValue(1)).toUpperCase().startsWith(" " + textFieldFilterSecondName.getText().toUpperCase());
                }
                if ((Long) spinnerFilterKarta.getModel().getValue() != 0) {
                    return (((Long) entry.getValue(0)).equals((Long) spinnerFilterKarta.getModel().getValue()));
                }
                if (!Uses.isNow((Date) spinnerFilterBirthday.getModel().getValue())) {
                    return ((Date) entry.getValue(3)).equals((Date) spinnerFilterBirthday.getModel().getValue());
                }
                if (!Uses.isNow((Date) spinnerFilterLastVisit.getModel().getValue())) {
                    return ((Date) entry.getValue(4)).equals((Date) spinnerFilterLastVisit.getModel().getValue());
                }
                return true;
            }
        };
        final TableRowSorter<TableModel> sorter = new TableRowSorter<>(tablePatients.getModel());
        sorter.setRowFilter(filter);
        tablePatients.setRowSorter(sorter);
        
        
        tablePatients.getColumnModel().getColumn(0).setPreferredWidth(150);
        tablePatients.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {

                if (tablePatients.getRowSorter().getViewRowCount() != 0 && e.getFirstIndex() >= 0 && e.getLastIndex() >= 0 && tablePatients.getSelectedRow() >= 0) {
                    if (tablePatients.getRowSorter() != null && tablePatients.getSelectedRow() != -1) {
                        int i = tablePatients.getRowSorter().convertRowIndexToModel(tablePatients.getSelectedRow());

                        final Long id = (Long) tablePatients.getModel().getValueAt(i, 0);
                        final Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
                        showPatientInfo(patient);

                    } else {
                        showPatientInfo(null);
                    }
                }
                if (tablePatients.getRowSorter().getViewRowCount() == 0) {
                    showPatientInfo(null);
                }
            }
        });
        if (tablePatients.getRowSorter().getViewRowCount() != 0) {
            tablePatients.getSelectionModel().addSelectionInterval(0, 0);
        }

        //***************************************************************************************
        //*** Visits
        tableVisits.getColumnModel().getColumn(0).setPreferredWidth(80);
        tableVisits.getColumnModel().getColumn(0).setWidth(80);
        if (tableVisits.getModel().getRowCount() != 0) {
            tableVisits.getSelectionModel().addSelectionInterval(0, 0);
        }
    }

    public void setTrueFocus() {
        tablePatients.requestFocusInWindow();
        tablePatients.requestFocus();
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = Diasled.getApplication().getMainFrame();
            aboutBox = new DiasledAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        Diasled.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        splitPanePatientsBase = new javax.swing.JSplitPane();
        panelPatientListArea = new javax.swing.JPanel();
        panelFilter = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        textFieldFilterSecondName = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        buttonApplyFilter = new javax.swing.JButton();
        buttonClearFilter = new javax.swing.JButton();
        spinnerFilterKarta = new javax.swing.JSpinner();
        spinnerFilterLastVisit = new javax.swing.JSpinner();
        spinnerFilterBirthday = new javax.swing.JSpinner();
        panelPatientsButtons = new javax.swing.JPanel();
        buttonEditPatient = new javax.swing.JButton();
        buttonAddPatient = new javax.swing.JButton();
        buttonRemoveParient = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        tablePatients = new javax.swing.JTable();
        panelPatientArea = new javax.swing.JPanel();
        panelPatientInfoButtons = new javax.swing.JPanel();
        buttonShowVisit = new javax.swing.JButton();
        buttonAddNewVisit = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        tableVisits = new javax.swing.JTable();
        jScrollPane3 = new javax.swing.JScrollPane();
        labelPatientInfo = new javax.swing.JLabel();
        labelVisitsCaption = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem6 = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();
        popupMenuPatients = new javax.swing.JPopupMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jMenuItem3 = new javax.swing.JMenuItem();
        popupMenuVisits = new javax.swing.JPopupMenu();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenuItem5 = new javax.swing.JMenuItem();

        mainPanel.setName("mainPanel"); // NOI18N

        splitPanePatientsBase.setDividerLocation(500);
        splitPanePatientsBase.setDividerSize(7);
        splitPanePatientsBase.setContinuousLayout(true);
        splitPanePatientsBase.setName("splitPanePatientsBase"); // NOI18N

        panelPatientListArea.setName("panelPatientListArea"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getResourceMap(DiasledView.class);
        panelFilter.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("panelFilter.border.title"))); // NOI18N
        panelFilter.setName("panelFilter"); // NOI18N

        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        textFieldFilterSecondName.setText(resourceMap.getString("textFieldFilterSecondName.text")); // NOI18N
        textFieldFilterSecondName.setName("textFieldFilterSecondName"); // NOI18N
        textFieldFilterSecondName.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                textFieldFilterSecondNameKeyReleased(evt);
            }
        });

        jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
        jLabel2.setName("jLabel2"); // NOI18N

        jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N
        jLabel3.setName("jLabel3"); // NOI18N

        jLabel4.setText(resourceMap.getString("jLabel4.text")); // NOI18N
        jLabel4.setName("jLabel4"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(ru.apertum.diasled.Diasled.class).getContext().getActionMap(DiasledView.class, this);
        buttonApplyFilter.setAction(actionMap.get("applyFilter")); // NOI18N
        buttonApplyFilter.setText(resourceMap.getString("buttonApplyFilter.text")); // NOI18N
        buttonApplyFilter.setName("buttonApplyFilter"); // NOI18N

        buttonClearFilter.setAction(actionMap.get("clearFilter")); // NOI18N
        buttonClearFilter.setText(resourceMap.getString("buttonClearFilter.text")); // NOI18N
        buttonClearFilter.setName("buttonClearFilter"); // NOI18N

        spinnerFilterKarta.setModel(new javax.swing.SpinnerNumberModel(Long.valueOf(0L), Long.valueOf(0L), null, Long.valueOf(1L)));
        spinnerFilterKarta.setName("spinnerFilterKarta"); // NOI18N

        spinnerFilterLastVisit.setModel(new javax.swing.SpinnerDateModel());
        spinnerFilterLastVisit.setEditor(new javax.swing.JSpinner.DateEditor(spinnerFilterLastVisit, "dd.MM.yyyy"));
        spinnerFilterLastVisit.setName("spinnerFilterLastVisit"); // NOI18N

        spinnerFilterBirthday.setModel(new javax.swing.SpinnerDateModel());
        spinnerFilterBirthday.setEditor(new javax.swing.JSpinner.DateEditor(spinnerFilterBirthday, "dd.MM.yyyy"));
        spinnerFilterBirthday.setName("spinnerFilterBirthday"); // NOI18N

        javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
        panelFilter.setLayout(panelFilterLayout);
        panelFilterLayout.setHorizontalGroup(
            panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelFilterLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2))
                .addGap(10, 10, 10)
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(panelFilterLayout.createSequentialGroup()
                        .addComponent(spinnerFilterKarta, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel4)
                        .addGap(10, 10, 10)
                        .addComponent(spinnerFilterLastVisit, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(textFieldFilterSecondName, javax.swing.GroupLayout.PREFERRED_SIZE, 192, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerFilterBirthday, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(29, 29, 29))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup()
                .addContainerGap(309, Short.MAX_VALUE)
                .addComponent(buttonClearFilter)
                .addGap(18, 18, 18)
                .addComponent(buttonApplyFilter)
                .addContainerGap())
        );
        panelFilterLayout.setVerticalGroup(
            panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelFilterLayout.createSequentialGroup()
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(spinnerFilterKarta, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(spinnerFilterLastVisit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(textFieldFilterSecondName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(spinnerFilterBirthday, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonApplyFilter)
                    .addComponent(buttonClearFilter))
                .addContainerGap())
        );

        panelPatientsButtons.setBorder(new javax.swing.border.MatteBorder(null));
        panelPatientsButtons.setName("panelPatientsButtons"); // NOI18N

        buttonEditPatient.setAction(actionMap.get("editPatient")); // NOI18N
        buttonEditPatient.setText(resourceMap.getString("buttonEditPatient.text")); // NOI18N
        buttonEditPatient.setName("buttonEditPatient"); // NOI18N

        buttonAddPatient.setAction(actionMap.get("addPatient")); // NOI18N
        buttonAddPatient.setText(resourceMap.getString("buttonAddPatient.text")); // NOI18N
        buttonAddPatient.setName("buttonAddPatient"); // NOI18N

        buttonRemoveParient.setAction(actionMap.get("removePotient")); // NOI18N
        buttonRemoveParient.setText(resourceMap.getString("buttonRemoveParient.text")); // NOI18N
        buttonRemoveParient.setName("buttonRemoveParient"); // NOI18N

        javax.swing.GroupLayout panelPatientsButtonsLayout = new javax.swing.GroupLayout(panelPatientsButtons);
        panelPatientsButtons.setLayout(panelPatientsButtonsLayout);
        panelPatientsButtonsLayout.setHorizontalGroup(
            panelPatientsButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPatientsButtonsLayout.createSequentialGroup()
                .addContainerGap(114, Short.MAX_VALUE)
                .addComponent(buttonRemoveParient)
                .addGap(18, 18, 18)
                .addComponent(buttonAddPatient)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonEditPatient)
                .addContainerGap())
        );
        panelPatientsButtonsLayout.setVerticalGroup(
            panelPatientsButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelPatientsButtonsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(panelPatientsButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonEditPatient)
                    .addComponent(buttonAddPatient)
                    .addComponent(buttonRemoveParient))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        tablePatients.setAutoCreateRowSorter(true);
        tablePatients.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"1323", "Иванов", "Петр Степанович", "13.10.1913", "13.12.2010"},
                {"3245", "Петров", "Сидор Михалыч", "12.10.1956", "31.12.2005"},
                {"144", "Сидоров", "Андрей Терентич", "25.01.2000", "21.05.2011"},
                {"634", "Путин", "Вэ.Вэ.", "16.09.1956", "04.12.2011"}
            },
            new String [] {
                "№", "Фамилия", "Имя, отчество", "Дата рождения", "Последний визит"
            }
        ));
        tablePatients.setComponentPopupMenu(popupMenuPatients);
        tablePatients.setName("tablePatients"); // NOI18N
        tablePatients.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        tablePatients.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tablePatientsMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(tablePatients);
        tablePatients.getColumnModel().getColumn(0).setPreferredWidth(25);
        tablePatients.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("tablePatients.columnModel.title0")); // NOI18N
        tablePatients.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("tablePatients.columnModel.title1")); // NOI18N
        tablePatients.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("tablePatients.columnModel.title2")); // NOI18N
        tablePatients.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("tablePatients.columnModel.title3")); // NOI18N
        tablePatients.getColumnModel().getColumn(4).setHeaderValue(resourceMap.getString("tablePatients.columnModel.title4")); // NOI18N

        javax.swing.GroupLayout panelPatientListAreaLayout = new javax.swing.GroupLayout(panelPatientListArea);
        panelPatientListArea.setLayout(panelPatientListAreaLayout);
        panelPatientListAreaLayout.setHorizontalGroup(
            panelPatientListAreaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelPatientsButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(panelFilter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 499, Short.MAX_VALUE)
        );
        panelPatientListAreaLayout.setVerticalGroup(
            panelPatientListAreaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPatientListAreaLayout.createSequentialGroup()
                .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(panelPatientsButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        splitPanePatientsBase.setLeftComponent(panelPatientListArea);

        panelPatientArea.setName("panelPatientArea"); // NOI18N

        panelPatientInfoButtons.setBorder(new javax.swing.border.MatteBorder(null));
        panelPatientInfoButtons.setName("panelPatientInfoButtons"); // NOI18N

        buttonShowVisit.setAction(actionMap.get("showVisit")); // NOI18N
        buttonShowVisit.setText(resourceMap.getString("buttonShowVisit.text")); // NOI18N
        buttonShowVisit.setName("buttonShowVisit"); // NOI18N

        buttonAddNewVisit.setAction(actionMap.get("addNewVisit")); // NOI18N
        buttonAddNewVisit.setName("buttonAddNewVisit"); // NOI18N

        javax.swing.GroupLayout panelPatientInfoButtonsLayout = new javax.swing.GroupLayout(panelPatientInfoButtons);
        panelPatientInfoButtons.setLayout(panelPatientInfoButtonsLayout);
        panelPatientInfoButtonsLayout.setHorizontalGroup(
            panelPatientInfoButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPatientInfoButtonsLayout.createSequentialGroup()
                .addContainerGap(94, Short.MAX_VALUE)
                .addComponent(buttonAddNewVisit)
                .addGap(18, 18, 18)
                .addComponent(buttonShowVisit)
                .addContainerGap())
        );
        panelPatientInfoButtonsLayout.setVerticalGroup(
            panelPatientInfoButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPatientInfoButtonsLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(panelPatientInfoButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonShowVisit)
                    .addComponent(buttonAddNewVisit))
                .addContainerGap())
        );

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        tableVisits.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"1", "20.05.2004", "Общее направление"},
                {"2", "14.06.2004", "Повторное обследование"},
                {"3", "13.12.2010", "Профилактика"},
                {null, null, null}
            },
            new String [] {
                "№", "Дата", "Описание"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tableVisits.setComponentPopupMenu(popupMenuVisits);
        tableVisits.setName("tableVisits"); // NOI18N
        tableVisits.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        tableVisits.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tableVisitsMouseClicked(evt);
            }
        });
        jScrollPane2.setViewportView(tableVisits);
        tableVisits.getColumnModel().getColumn(0).setPreferredWidth(15);
        tableVisits.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("tableVisits.columnModel.title0")); // NOI18N
        tableVisits.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("tableVisits.columnModel.title1")); // NOI18N
        tableVisits.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("tableVisits.columnModel.title2")); // NOI18N

        jScrollPane3.setBorder(null);
        jScrollPane3.setName("jScrollPane3"); // NOI18N

        labelPatientInfo.setText(resourceMap.getString("labelPatientInfo.text")); // NOI18N
        labelPatientInfo.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        labelPatientInfo.setBorder(new javax.swing.border.MatteBorder(null));
        labelPatientInfo.setName("labelPatientInfo"); // NOI18N
        jScrollPane3.setViewportView(labelPatientInfo);

        labelVisitsCaption.setFont(resourceMap.getFont("labelVisitsCaption.font")); // NOI18N
        labelVisitsCaption.setText(resourceMap.getString("labelVisitsCaption.text")); // NOI18N
        labelVisitsCaption.setName("labelVisitsCaption"); // NOI18N

        javax.swing.GroupLayout panelPatientAreaLayout = new javax.swing.GroupLayout(panelPatientArea);
        panelPatientArea.setLayout(panelPatientAreaLayout);
        panelPatientAreaLayout.setHorizontalGroup(
            panelPatientAreaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelPatientInfoButtons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(panelPatientAreaLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                .addContainerGap())
            .addGroup(panelPatientAreaLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(labelVisitsCaption)
                .addContainerGap(255, Short.MAX_VALUE))
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
        );
        panelPatientAreaLayout.setVerticalGroup(
            panelPatientAreaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelPatientAreaLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(labelVisitsCaption)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 184, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(panelPatientInfoButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        splitPanePatientsBase.setRightComponent(panelPatientArea);

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(splitPanePatientsBase, javax.swing.GroupLayout.DEFAULT_SIZE, 908, Short.MAX_VALUE)
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(splitPanePatientsBase, javax.swing.GroupLayout.DEFAULT_SIZE, 526, Short.MAX_VALUE)
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        jMenu1.setText(resourceMap.getString("jMenu1.text")); // NOI18N
        jMenu1.setName("jMenu1"); // NOI18N

        jMenuItem6.setAction(actionMap.get("showConfig")); // NOI18N
        jMenuItem6.setName("jMenuItem6"); // NOI18N
        jMenu1.add(jMenuItem6);

        menuBar.add(jMenu1);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 908, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 738, Short.MAX_VALUE)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        popupMenuPatients.setName("popupMenuPatients"); // NOI18N

        jMenuItem1.setAction(actionMap.get("addPatient")); // NOI18N
        jMenuItem1.setName("jMenuItem1"); // NOI18N
        popupMenuPatients.add(jMenuItem1);

        jMenuItem2.setAction(actionMap.get("editPatient")); // NOI18N
        jMenuItem2.setName("jMenuItem2"); // NOI18N
        popupMenuPatients.add(jMenuItem2);

        jSeparator1.setName("jSeparator1"); // NOI18N
        popupMenuPatients.add(jSeparator1);

        jMenuItem3.setAction(actionMap.get("removePotient")); // NOI18N
        jMenuItem3.setName("jMenuItem3"); // NOI18N
        popupMenuPatients.add(jMenuItem3);

        popupMenuVisits.setName("popupMenuVisits"); // NOI18N

        jMenuItem4.setAction(actionMap.get("showVisit")); // NOI18N
        jMenuItem4.setName("jMenuItem4"); // NOI18N
        popupMenuVisits.add(jMenuItem4);

        jMenuItem5.setAction(actionMap.get("addNewVisit")); // NOI18N
        jMenuItem5.setName("jMenuItem5"); // NOI18N
        popupMenuVisits.add(jMenuItem5);

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void tablePatientsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tablePatientsMouseClicked
        if (tablePatients.getRowSorter() != null && tablePatients.getSelectedRow() != -1) {
            int i = tablePatients.getRowSorter().convertRowIndexToModel(tablePatients.getSelectedRow());

            final Long id = (Long) tablePatients.getModel().getValueAt(i, 0);
            final Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
            showPatientInfo(patient);
        } else {
            showPatientInfo(null);
        }




        //final Long id = (Long) tablePatients.getModel().getValueAt(tablePatients.getSelectedRow(), 0);
        //Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
        //       showPatientInfo(patient);
        if (evt.getClickCount() > 1) {
            editPatient();
        }
    }//GEN-LAST:event_tablePatientsMouseClicked

    private void tableVisitsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableVisitsMouseClicked
        if (evt.getClickCount() > 1) {
            showVisit();
        }
    }//GEN-LAST:event_tableVisitsMouseClicked

    private void textFieldFilterSecondNameKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_textFieldFilterSecondNameKeyReleased
        applyFilter();
    }//GEN-LAST:event_textFieldFilterSecondNameKeyReleased

    @Action
    public void addPatient() {
        final Patient patient = FPatientEditor.editPatient(null);
        if (patient != null) {
            ((PatientsTableModel) tablePatients.getModel()).add(patient);
            try {
                Patient.savePatient(patient);
            } catch (Uses.ClientException ex) {
                JOptionPane.showMessageDialog(this.getFrame(),
                        "Ошибка сохранения ппациента.",
                        "Сохранение",
                        JOptionPane.ERROR_MESSAGE);
                return;
            }
            ((PatientsTableModel) tablePatients.getModel()).fireTableDataChanged();
            selectTablePatientsItem(patient);
        }
    }

    @Action
    public void editPatient() {
        if (!tablePatients.getSelectionModel().isSelectionEmpty()) {
            final Long id = (Long) tablePatients.getModel().getValueAt(tablePatients.getSelectedRow(), 0);
            Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
            patient = FPatientEditor.editPatient(patient);
            if (patient != null) {
                try {
                    Patient.savePatient(patient);
                } catch (Uses.ClientException ex) {
                    JOptionPane.showMessageDialog(this.getFrame(),
                            "Ошибка сохранения ппациента.",
                            "Сохранение",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
                ((PatientsTableModel) tablePatients.getModel()).fireTableDataChanged();
                selectTablePatientsItem(patient);
            }
        }
    }

    @Action
    public void removePotient() {
        if (!tablePatients.getSelectionModel().isSelectionEmpty()) {
            final Long id = (Long) tablePatients.getModel().getValueAt(tablePatients.getSelectedRow(), 0);
            final Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
            if (patient == null || JOptionPane.showConfirmDialog(this.getFrame(),
                    "Пациент \"" + patient.getName() + "\" будет удален безвозвратно?",
                    "Удаление пациента",
                    JOptionPane.YES_NO_OPTION) == 1) {
                return;
            }
            Uses.log.logger.debug("Удаляем пользователя \"" + patient.getName() + "\"");
            int i = tablePatients.getSelectedRow();
            // удалим навсегда
            ((PatientsTableModel) tablePatients.getModel()).removePatient(patient);
            // в фокус запись рядом
            if (tablePatients.getRowCount() != 0) {
                if (tablePatients.getRowCount() - 1 < i) {
                    i--;
                }
                tablePatients.getSelectionModel().setSelectionInterval(i, i);
            }
        }
    }

    /**
     * Выделить в таблице строку с пациентом
     * @param patient 
     */
    public void selectTablePatientsItem(Patient patient) {
        for (int i = 0; i < tablePatients.getModel().getRowCount(); i++) {
            if ((Long) tablePatients.getModel().getValueAt(i, 0) == patient.getId()) {
                tablePatients.getSelectionModel().addSelectionInterval(i, i);
                showPatientInfo(patient);
                break;
            }
        }
    }

    /**
     * выведем инфу о пациенте в область информации о пациенте
     * @param patient 
     */
    public void showPatientInfo(Patient patient) {
        if (patient == null) {
            labelPatientInfo.setText("");
            ((VisitsTableModel) tableVisits.getModel()).update(null, null);
        } else {
            labelPatientInfo.setText("<html>" + patient.getTextInfo());
            ((VisitsTableModel) tableVisits.getModel()).update(patient, patient.getVisits());
        }
        ((VisitsTableModel) tableVisits.getModel()).fireTableDataChanged();
        if (tablePatients.getRowSorter().getViewRowCount() != 0) {
            tableVisits.getSelectionModel().addSelectionInterval(0, 0);
        }
    }

    @Action
    public void addNewVisit() {
        final Patient patient = ((VisitsTableModel) tableVisits.getModel()).getPatient();
        if (patient != null) {
            // если сегодня уже создали визит тое го не нужно еще раз создавать, просто покажем его
            Visit visit = ((VisitsTableModel) tableVisits.getModel()).getVisitByDate(new Date());
            if (visit == null) {
                if (JOptionPane.showConfirmDialog(this.getFrame(),
                        "Будет создано новое посещение для пациента \"" + patient.getName() + "\"?",
                        "Новое посещение",
                        JOptionPane.YES_NO_OPTION) == 1) {
                    return;
                }
                patient.getVisits().add(visit = new Visit(patient));
                patient.setLastVisit(new Date());
                try {
                    Patient.savePatient(patient);
                } catch (Uses.ClientException ex) {
                    JOptionPane.showMessageDialog(this.getFrame(),
                            "Ошибка создания посещения.",
                            "Сохранение посещения",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }

                ((VisitsTableModel) tableVisits.getModel()).update(patient, patient.getVisits());
                ((VisitsTableModel) tableVisits.getModel()).fireTableDataChanged();
            }
            final FVisitEditor ve = new FVisitEditor(visit, tableVisits.getModel());
            ve.setLocationRelativeTo(null);
            ve.setVisible(true);
        }
    }

    @Action
    public void showVisit() {
        if (!tableVisits.getSelectionModel().isSelectionEmpty()) {
            final Date date = (Date) tableVisits.getModel().getValueAt(tableVisits.getSelectedRow(), 1);
            final Visit visit = ((VisitsTableModel) tableVisits.getModel()).getVisitByDate(date);
            final FVisitEditor ve = new FVisitEditor(visit, tableVisits.getModel());
            ve.setLocationRelativeTo(null);
            ve.setVisible(true);
        }
    }

    @Action
    public void clearFilter() {
        /*
        FExamination fe= FExamination.getInstance();
        fe.setVisible(true);
        if (true) {
        return;
        }
         */
        spinnerFilterBirthday.getModel().setValue(new Date());
        spinnerFilterLastVisit.getModel().setValue(new Date());
        spinnerFilterKarta.getModel().setValue(new Long(0));
        textFieldFilterSecondName.setText(null);
        /*
        ((PatientsTableModel) tablePatients.getModel()).filter(null);
         * 
         */
        ((PatientsTableModel) tablePatients.getModel()).fireTableDataChanged();

        if (tablePatients.getRowSorter().getViewRowCount() != 0) {
            tablePatients.getSelectionModel().addSelectionInterval(0, 0);
            final Long id = (Long) tablePatients.getModel().getValueAt(0, 0);
            final Patient patient = ((PatientsTableModel) tablePatients.getModel()).getPatientById(id);
            showPatientInfo(patient);
        } else {
            showPatientInfo(null);
        }
    }

    @Action
    public void applyFilter() {
        ((PatientsTableModel) tablePatients.getModel()).fireTableDataChanged();
        /*
        final HashMap<String, Object> filter = new HashMap<>();
        if (!textFieldFilterSecondName.getText().isEmpty()) {
        filter.put("secondName", textFieldFilterSecondName.getText());
        }
        if ((Integer) spinnerFilterKarta.getModel().getValue() != 0) {
        filter.put("id", new Long((Integer) spinnerFilterKarta.getModel().getValue()));
        }
        if (!Uses.isNow((Date) spinnerFilterBirthday.getModel().getValue())) {
        filter.put("birthday", spinnerFilterBirthday.getModel().getValue());
        }
        if (!Uses.isNow((Date) spinnerFilterLastVisit.getModel().getValue())) {
        filter.put("lastVisit", spinnerFilterLastVisit.getModel().getValue());
        }
        ((PatientsTableModel) tablePatients.getModel()).filter(filter);
        ((PatientsTableModel) tablePatients.getModel()).fireTableDataChanged();
         * 
         */
        if (tablePatients.getRowSorter().getViewRowCount() != 0) {
            tablePatients.getSelectionModel().addSelectionInterval(0, 0);
        }

    }

    @Action
    public void showConfig() {
        FConfigDev.getInstance().load();
        FConfigDev.getInstance().setVisible(true);
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonAddNewVisit;
    private javax.swing.JButton buttonAddPatient;
    private javax.swing.JButton buttonApplyFilter;
    private javax.swing.JButton buttonClearFilter;
    private javax.swing.JButton buttonEditPatient;
    private javax.swing.JButton buttonRemoveParient;
    private javax.swing.JButton buttonShowVisit;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem5;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JLabel labelPatientInfo;
    private javax.swing.JLabel labelVisitsCaption;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JPanel panelFilter;
    private javax.swing.JPanel panelPatientArea;
    private javax.swing.JPanel panelPatientInfoButtons;
    private javax.swing.JPanel panelPatientListArea;
    private javax.swing.JPanel panelPatientsButtons;
    private javax.swing.JPopupMenu popupMenuPatients;
    private javax.swing.JPopupMenu popupMenuVisits;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JSpinner spinnerFilterBirthday;
    private javax.swing.JSpinner spinnerFilterKarta;
    private javax.swing.JSpinner spinnerFilterLastVisit;
    private javax.swing.JSplitPane splitPanePatientsBase;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JTable tablePatients;
    private javax.swing.JTable tableVisits;
    private javax.swing.JTextField textFieldFilterSecondName;
    // End of variables declaration//GEN-END:variables
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;
}
